package com.yunxun.coinmessage.service;

import com.yunxun.coinmessage.config.ConfigJson;
import com.yunxun.coinmessage.dao.ContentDao;
import com.yunxun.coinmessage.entity.Coin;
import com.yunxun.coinmessage.entity.Content;
import com.yunxun.coinmessage.entity.Exchange;
import com.yunxun.coinmessage.entity.Program;
import com.yunxun.coinmessage.templatedata.CoinTemplateData;
import com.yunxun.coinmessage.templatedata.ContentConditionTemplateData;
import com.yunxun.coinmessage.templatedata.ContentTamplateData;
import com.yunxun.coinmessage.templatedata.MsgResult;
import com.yunxun.coinmessage.sqlvo.ContentVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindingResult;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class ContentService {
    @Autowired
    ContentDao contentDao;
    @Autowired
    ProgramService programService;
    @Autowired
    CoinService coinService;
    @Autowired
    ExchangeService exchangeService;
    @Autowired
    private Environment env;
    @Autowired
    private PushListService pushListService;
    private MsgResult msgResult;
    private Map<String,String> map;//存储图片原来路径和上传后的路径为一键值对
    private String imageRootPath;//上传图片的根路径
    public List<ContentTamplateData> queryByPage(ContentVO contentVO){
        List<Content> contentList= contentDao.queryByPage(contentVO);
        List<ContentTamplateData> contentTamplateDataList =new ArrayList<ContentTamplateData>();//返回给content-list页面的模型
        for(Content content:contentList){
            ContentTamplateData contentTamplateData =new ContentTamplateData();
            //格式化时间戳
            SimpleDateFormat format =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Long time=content.getCreate_time()*1000;
            Date date=new Date(time);
            String formatTime=format.format(date);
            contentTamplateData.setFormatTime(formatTime);
            //根据program_id查找栏目名称
            Program program= programService.queryById(content.getProgram_id());
            contentTamplateData.setProgram(program);
            //对标题中含有html标签"<"和">"进行转义
            String con_title=content.getCon_title().replaceAll("<","&lt");
            con_title=con_title.replaceAll(">","&gt");
            content.setCon_title(con_title);
            contentTamplateData.setContent(content);
            //用于分页查询时能够带上条件
            contentTamplateData.setContentVO(contentVO);
            //根据coin_id和exchange_id查找
            if (content.getCoin_id()!=0) {
                Coin coin=coinService.queryById(content.getCoin_id());
                contentTamplateData.setCoin(coin);
            }
            if(content.getExchange_id()!=0) {
                Exchange exchange = exchangeService.queryById(content.getExchange_id());
                contentTamplateData.setExchange(exchange);
            }
            contentTamplateDataList.add(contentTamplateData);
        }
        return contentTamplateDataList;

    }

    public Content queryContentById(Integer con_id){
        return contentDao.queryContentById(con_id);
    }



    /**
     * 组合条件下拉选内容
     * @return
     */
    public ContentConditionTemplateData getContentConditionModel(){
        ContentConditionTemplateData contentConditionTemplateData =new ContentConditionTemplateData();
        List<Program> programList=programService.queryAll();
        List<Coin> coinList=coinService.queryAll();
        List<CoinTemplateData> coinTemplateDataList=new ArrayList<>();
        for(Coin coin:coinList){
            CoinTemplateData coinTemplateData=new CoinTemplateData();
            coinTemplateData.setSelectCoin("("+coin.getCcode().toLowerCase()+")"+coin.getCname());
            coinTemplateData.setCid(coin.getCid());
            coinTemplateDataList.add(coinTemplateData);
        }
        List<Exchange> exchangeList=exchangeService.queryAll();
        HashMap map=new HashMap();
        map.put(1,"未审核");
        map.put(2,"已发布");
        map.put(3,"已删除");
        contentConditionTemplateData.setProgramList(programList);
        contentConditionTemplateData.setCoinList(coinList);
        contentConditionTemplateData.setExchangeList(exchangeList);
        contentConditionTemplateData.setStatusMap(map);
        contentConditionTemplateData.setCoinTemplateDataList(coinTemplateDataList);
        return contentConditionTemplateData;
    }
    public Integer queryTotal(){
        return contentDao.queryTotal();
    }

    public int queryTotalByCondition(ContentVO contentVO){
        return contentDao.queryTotalByCondition(contentVO);
    }

    /**
     * 手动新增资讯
     * @param content
     * @throws Exception
     */
    public int addContent( Content content)throws Exception{
        String md5Article=getMd5Article(content.getCon_article());
        content.setVerifycode(md5Article);
        if(contentDao.queryByVerifycode(md5Article)>0){
            throw new Exception("该条资讯已存在");
        }else if(contentDao.queryContentByName(content.getCon_title())>0){
            throw new Exception("标题重复");
        }
        content.setStatus(2);
        int tag=contentDao.addConten(content);
        if(tag>0){
            pushListService.addPushList(content);
        }
        return  tag;
    }

    /**
     * 通过采集方式新增资讯
     * @param content
     * @return
     */
    public MsgResult addContentByCollector(Content content) {
        if(StringUtils.isEmpty(content.getCon_title())){
            return new MsgResult(false,"标题为空");
        }
        int coinId=0;
        int max=0;//找出币种中文名称，简称或英文名称在标题或文章中出现次数的最大值。
        //去掉空白内容的快讯
        if(content.getProgram_id() == 1){
            String article=content.getCon_article().replaceAll("<.*?>","");
            if(article.length() < 5){
                return new MsgResult(false,"该快讯内容为空");
            }
        }
        if (content.getCoin_id() == 0) {
            // 先查询全部币种
            // 中文名称，简称，英文名称
            // 循环
            //   标题出现
            //   内容出现
            List<Coin> coinList=coinService.queryAll();
            for(Coin coin:coinList){
                if(max<getMaxCount(coin,content)){
                    max=getMaxCount(coin,content);
                    coinId=coin.getCid();
                }
            }
            content.setCoin_id(coinId);
        }
        content.setStatus(2);

        if(contentDao.queryByVerifycode(content.getVerifycode())>0){
            return new MsgResult(false,"该条资讯已存在");
        }
        String con_article=content.getCon_article();
        //获得con_article中所有image中src=""，下载图片,并返回替换了src的con_article;
        con_article=getImageSrc(con_article,content.getCon_addr());
        //将替换了src的值设置进content
        content.setCon_article(con_article);
        int tag=contentDao.addContenByCollector(content);
        if(tag!=0){
            pushListService.addPushList(content);
            return new MsgResult(true,"添加成功");
        }
        return new MsgResult(false,"添加失败");
    }

    public  MsgResult updateContentById(Content content){
        int tag;
        //用con_id寻找一篇资讯，查询到的资讯标题与传入的资讯标题一致，那么这种情况就是编辑时未更改标题
        if(contentDao.queryContentById(content.getCon_id()).getCon_title().equals(content.getCon_title())){
            tag=contentDao.updateContentById(content);
            if(tag>0){
                return new MsgResult(true,"更新成功");

            }else {
                return new MsgResult(true,"更新失败，请重新尝试");
            }
        }else{//不一致则是修改了标题，则用标题查询是否一样的标题
            if(contentDao.queryContentByName(content.getCon_title())>0){
                return new MsgResult(false,"标题重复，更新失败");
            }else {
                tag=contentDao.updateContentById(content);
                if(tag>0){
                    return new MsgResult(true,"更新成功");

                }else {
                    return new MsgResult(true,"更新失败，请重新尝试");
                }
            }
        }
    }

    public MsgResult updateStatus(Integer con_id,Integer status){
         int tag;
        if (status == 3) {
            tag=contentDao.updateStatus(con_id, status);
            if(tag>0){
                 msgResult=new MsgResult(true,"删除成功");
                 return msgResult;
            }else {
                msgResult=new MsgResult(false,"删除失败，请重新尝试");
                return msgResult;
            }
        }else if(status==1 || status==2){
            if(status==2){
                Content content=contentDao.queryContentById(con_id);
                //防止已审核通过的文章进入推送列表，推送用户两次
                if(content.getStatus()!=2){
                    pushListService.addPushList(content);
                }
            }
            tag=contentDao.updateStatus(con_id, status);
            if(tag>0){
                msgResult=new MsgResult(true,"修改文章状态成功");
                return msgResult;
            }else{
                msgResult=new MsgResult(false,"修改文章状态失败");
                return msgResult;
            }
        }else {
                msgResult=new MsgResult(true,"未知状态，不可修改");
                return msgResult;
                }
        }
   public  String getMd5Article(String article) {
        try {
            // 得到一个信息摘要器
            MessageDigest digest = MessageDigest.getInstance("md5");
            byte[] result = digest.digest(article.getBytes());
            StringBuffer buffer = new StringBuffer();
            // 把每一个byte 做一个与运算 0xff;
            for (byte b : result) {
                // 与运算
                int number = b & 0xff;// 加盐
                String str = Integer.toHexString(number);
                if (str.length() == 1) {
                    buffer.append("0");
                }
                buffer.append(str);
            }

            // 标准的md5加密后的结果
            return buffer.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return "";
        }

    }


    /**
     * 找到原文所有的img标签并返回提换了img标签data-src的原文
     * @param con_article
     * @param con_addr
     * @return
     */
    public String getImageSrc(String con_article,String con_addr){
        map=new HashMap<>();
        //用于拼接(src=|data-src=|origin-src=)("|')(.*?)("|')匹配到的内容
        List<String> list = new ArrayList<String>();
            //目前img标签标示有3种表达式
            //<img alt="" src="1.jpg"/> <img alt="" src="1.jpg"></img> <img alt="" src="1.jpg">
            //开始匹配content中的<img />标签
        Pattern p_img = Pattern.compile("<(img|IMG)(.*?)(/>|></img>|>)");
        Matcher m_img = p_img.matcher(con_article);
        boolean result_img = m_img.find();
        if (result_img) {
            while (result_img) {
                    //获取到匹配的<img />标签中的内容
                String str_img = m_img.group(2);
                    //开始匹配<img />标签中的src
                Pattern p_src = Pattern.compile("(src=|data\\-src=|origin\\-src=)(\"|\')(.*?)(\"|\')");
                Matcher m_src = p_src.matcher(str_img);
                if (m_src.find()) {
                    //<image>标签中的src=""或data-src=""
                    String imageSrc=m_src.group(1)+m_src.group(2)+m_src.group(3)+m_src.group(4);
                    //图片url
                    String imageUrl = m_src.group(3);//src中的内容
                    //下载图片,并替换<img>标签的原src内容。
                    con_article= downImages(imageSrc,imageUrl,con_addr,con_article);
                }

                result_img = m_img.find();
            }
        }
        return con_article;
    }

    /**
     * 下载图片，将data-src=""替换成src="",并将替换了原文内容返回
     * @param imageSrc 图片标签data-src
     * @param imageUrl 图片的url
     * @param con_addr 原文url地址
     * @param con_article 原文
     * @return 替换成功后的原文内容
     */

    public  String downImages(String imageSrc,String imageUrl,String con_addr,String con_article){
        // 截取图片的后缀
         String  suffix = ".jpg";
         if(imageUrl.toLowerCase().contains("jpeg")){
             suffix=".jpeg";
         }
        if(imageUrl.toLowerCase().contains("bmp")){
            suffix=".bmp";
        }
        if(imageUrl.toLowerCase().contains("png")){
            suffix=".png";
        }
        if(imageUrl.toLowerCase().contains("gif")){
             suffix=".gif";
        }
        //带图片名称的真实路径
       String imageRealPath=this.getImageRealPath(suffix);
        //截取文件名之前的内容，判断是否存在该文件夹，不存在则创建。
        String createFile=imageRealPath.substring(0,imageRealPath.lastIndexOf("/"));
        File files = new File(createFile);
        if(!files.exists()){// 判断文件夹是否存在，如果不存在就创建一个文件夹
            files.mkdirs();
        }
        try {
            //为省略了http或域名的http加上省略的内容
            if(imageUrl.startsWith("//")){
                String prefix=con_addr.substring(0,con_addr.indexOf("//"));
                imageUrl=prefix+imageUrl;
            }
            if(imageUrl.startsWith("/")){
                //协议
               String start=con_addr.substring(0,con_addr.indexOf("//"));
               //域名http://www.baidu.com/index.jsp
               //记录双斜杠出现的位置
               int index=con_article.indexOf("//")+2;
               String body=con_addr.substring(index,con_addr.indexOf("/",index));
               imageUrl=start+body+imageUrl;
            }
            URL url = new URL(imageUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            InputStream is = connection.getInputStream();
            // 创建文件
            File file = new File(imageRealPath);
            FileOutputStream out = new FileOutputStream(file);
            int i = 0;
            while((i = is.read()) != -1){
                out.write(i);
            }
            is.close();
            out.close();
        } catch (Exception e) {
            //如果抛出异常，不替换原data-src成相对路径并返回原文
            e.printStackTrace();
            return con_article;
        }
        //将con_articl中的原data-src替换成相对路径并返回原文
        con_article=con_article.replace(imageSrc,"src="+imageRealPath.replace(imageRootPath,""));
        return con_article;
    }
    /**
     * 获得要上传图片的真实路径
     * @return
     */
    public String getImageRealPath(String suffix){
        String configPath=env.getProperty("configjson.path");
        ConfigJson configJson=new ConfigJson();
        //得到上传图片的根路径
        imageRootPath=configJson.getImageRealPath(configPath);
        Long timeStamp=System.currentTimeMillis();
        SimpleDateFormat format =  new SimpleDateFormat("yyyyMMdd");
        Date date=new Date(timeStamp);
        String formatTime=format.format(date);
        String random=getRandom();
        String imageRealPath=imageRootPath+"/image/"+formatTime+"/"+timeStamp+random+suffix;
        return imageRealPath;
    }
    //生成6位随机数
    private  String getRandom ( ) {
        String s = "";
        while(s.length()<6){
            s+=(int)(Math.random()*10);
        }
        return s;
    }
    public int queryContentByVerifycode(String verifycode){
        return contentDao.queryByVerifycode(verifycode);
    }
    /**
     * 得到币种简称，中文名称，英文名称三者中出现次数最多的一种为币种的最关键的属行
     * @param coin
     * @param content
     * @return
     */
    public int getMaxCount(Coin coin,Content content){
        int max=0;
        //增加标题出现次数的权重，出现一次就为2次
        max= appearNumber(coin.getCname(),content.getCon_title())*2;
        if(max<appearCcodeCount(coin.getCcode(),content.getCon_title())*2){
            max=appearCcodeCount(coin.getCcode(),content.getCon_title())*2;
        }
        if(max<appearNumber(coin.getEnglish_name(),content.getCon_title())*2){
            max=appearNumber(coin.getEnglish_name(),content.getCon_title())*2;
        }
        //判断在内容中出现的次数
        if(max<appearNumber(coin.getCname(),content.getCon_article())){
            max=appearNumber(coin.getCname(),content.getCon_article());
        }
        if (max<appearCcodeCount(coin.getCcode(),content.getCon_article())){
            max=appearCcodeCount(coin.getCcode(),content.getCon_article());
        }
        if(max<appearNumber(coin.getEnglish_name(),content.getCon_article())){
            max=appearNumber(coin.getEnglish_name(),content.getCon_article());
        }
        return max;
    }
    /**
     * 用于统计币种中文名称，简称或英文名称在标题或文章中出现次数
     * @param srcText
     * @param findText
     * @return
     */
    public  int appearNumber(String srcText, String findText) {
        srcText =srcText.toLowerCase();
        findText=findText.toLowerCase();
        int count = 0;
        Pattern p = Pattern.compile(srcText);
        Matcher m = p.matcher(findText);
        while (m.find()) {
            count++;
        }
        return count;
    }
    public int appearCcodeCount(String srcText,String findText){
        findText="开始"+findText;
        srcText =srcText.toLowerCase();
        findText=findText.toLowerCase();
        int count = 0;
        String s = "([^a-zA-Z]|\\s)"+srcText+"[^a-zA-Z]?";
        Pattern p = Pattern.compile(s);
        Matcher m = p.matcher(findText);
        while (m.find()) {
            count++;
        }
        return count;
    }

}
